package {{.package}}

import (
	"context"
	"gorm.io/gorm"
)

type (
	{{.model}}Model interface {
		Insert(ctx context.Context, data *{{.model}}) error
		FindOne(ctx context.Context, id {{.primaryKeyType}}) (*{{.model}}, error)
		ListByIds(ctx context.Context, ids []{{.primaryKeyType}}) ([]*{{.model}}, int64, error)
		Update(ctx context.Context, data *{{.model}}) error
		Delete(ctx context.Context, id {{.primaryKeyType}}) error
	}

	default{{.model}} struct {
		db *gorm.DB
	}
)

func New{{.model}}Model(db *gorm.DB) {{.model}}Model {
	return &default{{.model}}{
		db: db,
	}
}

func (m *default{{.model}}) model() *gorm.DB {
	return m.db.Model(&{{.model}}{})
}

func (m *default{{.model}}) Insert(ctx context.Context, data *{{.model}}) error {
	return m.db.Create(data).Error
}

func (m *default{{.model}}) FindOne(ctx context.Context, id {{.primaryKeyType}}) (*{{.model}}, error) {
	var res {{.model}}
	err := m.db.First(&res, "{{.primaryKey}} = ?", id).Error

	switch err {
    case nil:
        return &res, nil
    case gorm.ErrRecordNotFound:
        return nil, ErrNotFound
    default:
        return nil, err
    }
}

func (m *default{{.model}}) ListByIds(ctx context.Context, ids []{{.primaryKeyType}}) ([]*{{.model}}, int64, error) {
	var (
		res   []*{{.model}}
		count int64
	)

	err := m.db.Find(&res, "{{.primaryKey}} in ?", ids).Error
	if err != nil {
		return nil, 0, err
	}

	err = m.model().Where("{{.primaryKey}} in ?", ids).Count(&count).Error
	if err != nil {
		return nil, 0, err
	}

	return res, count, nil
}

func (m *default{{.model}}) Update(ctx context.Context, data *{{.model}}) error {
	return m.db.Save(data).Error
}

func (m *default{{.model}}) Delete(ctx context.Context, id {{.primaryKeyType}}) error {
	return m.db.Delete(&{{.model}}{}, "{{.primaryKey}} = ?", id).Error
}
